#-*- coding: utf-8 -*-
 
import logging,random,uuid,string,time
import tornado.escape
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.websocket
import os.path
 
from tornado.web import HTTPError
from session.auth import MongoAuthentication
from session.session import MongoSessions
from BaseHandler import BaseHandler
from tornado.options import define, options
from verify_code import make as make_verify_code
 
define("port", default=8888, help="run on the given port", type=int)
 
'''
    开发人：
        ROY (火炎神)
    时间：
        2014/6/14
 
    服务端的架构体系：
        db  : newjh (mongodb)
        b/s : websocket
        session : 基于mongodb
        verify_code : 校验码验证
'''
 
class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r"/register",RegisterHandler),
            (r"/login",LoginHandler),
            (r"/logout",LogoutHandler),
            (r"/", MainHandler),
            (r"/chatsocket", ChatSocketHandler),
            (r"/verifycode",VerifyCode),
        ]
        settings = dict(
            cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__",
            template_path=os.path.join(os.path.dirname(__file__), "templates"),
            static_path=os.path.join(os.path.dirname(__file__), "static"),
            xsrf_cookies=False,
        )
 
        self.sessions = MongoSessions("newjh", "sessions", timeout=10)
        self.auth = MongoAuthentication("newjh", "user")
        self.sessions.clear_all_sessions()
        tornado.web.Application.__init__(self, handlers, **settings)
 
class RegisterHandler(BaseHandler):
    def get(self):
        self.render("register.html")
    def post(self):
        username = self.get_argument('username',None)
        _username = self.get_argument('_username',None)
        pwd = self.get_argument('pwd',None)
        #pwd = md5(pwd).hexdigest()
        print 'argument %s'%self.request.arguments
        user = self.db.user.find_one({'uid':username})
        if user :
            self.write("帐号已经注册了")
        else:
            code = self.get_argument('code',None)
            cookiecode = self.get_secure_cookie('verify_code')
            print 'register code / server code',code,cookiecode
            if code != cookiecode : raise HTTPError(403,'验证不对')
            user = {
                'uid':username,
                'pwd':pwd,
                'name':_username,
                'gold':100000,
                'gamegold':0,
                'jewel':0,
                'regtime':time.strftime('%Y-%m-%d',time.localtime(time.time())),
                'bind':{'email':0,'mobile':0,'sec':0,'idcard':0},
                'sign':{},
                'signnum':{},
            }
            print 'user%s'%user
            res = self.application.auth.register(user)
            if not res : raise HTTPError(403)
            #user = db.user.find_one({'uid':username})
            res = self.begin_session(username,pwd)
            if not res : raise HTTPError(403)
            self.redirect('/login')
 
class LoginHandler(BaseHandler):
    def post(self):
        print self.request
        name = self.get_argument('name',None)
        pwd = self.get_argument('pwd',None)
        logging.info(('loging name pwd %s %s'%(name,pwd)))
        code = self.get_argument('code',None)
        cookiecode = self.get_secure_cookie('verify_code')
        print 'verify code cookie',cookiecode
        if code != cookiecode : raise HTTPError(403)
        res = self.begin_session(name, pwd)
        if not res : raise HTTPError(403)
        self.redirect('/')
    def get(self):
        self.render("login.html")
 
class LogoutHandler(BaseHandler):
    def get(self):
        self.post()
 
    def post(self):
        self.end_session()
        self.redirect('/login')
 
 
class VerifyCode(BaseHandler):
    def get(self):
        verify_code = ''.join(random.sample(string.ascii_lowercase\
                      +string.digits,4))
        self.set_secure_cookie("verify_code",verify_code)
        content = make_verify_code(verify_code)
        self.set_header('Content-Type','image/jpeg;charset=utf-8')
        self.write(content)
 
class MainHandler(BaseHandler):
    def get(self):
 
        if self.session :
            _user = self.session['data']
            self.render("index.html",
                        messages=ChatSocketHandler.cache,
                        userlist=ChatSocketHandler.userlist,
                        myuser = _user)
        else:
            self.redirect('/login')
 
class ChatSocketHandler(tornado.websocket.WebSocketHandler):
    waiters = set()
    cache = []
    cache_size = 200
 
    userlist = []
    user_size = 100
    user = None
 
 
    def allow_draft76(self):
        # for iOS 5.0 Safari
        return True
 
    def open(self):
        print 'open... is start '
        #self.on_message({"name":"roy","body":"welcome roy !","type":1})
        ChatSocketHandler.waiters.add(self)
        #self.write_message("ok!")
 
    def on_close(self):
        for i in ChatSocketHandler.userlist:
            if (self.user["content"] == i["content"]) :
                ChatSocketHandler.userlist.remove(i)
        print self.user
        self.user["type"] = 3
        user = self.user
        self.user = None
        ChatSocketHandler.waiters.remove(self)
        ChatSocketHandler.send_updates(user)
 
    @classmethod
    def update_cache(cls, chat):
        cls.cache.append(chat)
        if len(cls.cache) > cls.cache_size:
            cls.cache = cls.cache[-cls.cache_size:]
 
    @classmethod
    def update_user(cls, user):
        for i in cls.userlist:
            if (user["content"] == i["content"]) : return
        #print cls.userlist
        #self.user = user
        cls.userlist.append(user)
        if len(cls.userlist) > cls.user_size:
            cls.userlist = cls.userlist[-cls.user_size:]
 
    @classmethod
    def send_updates(cls, chat):
        logging.info("sending message to %d waiters", len(cls.waiters))
        for waiter in cls.waiters:
            try:
                waiter.write_message(chat)
            except:
                logging.error("Error sending message", exc_info=True)
 
 
    def on_message(self, message):
        logging.info("got message %r", message)
        parsed = tornado.escape.json_decode(message)
        if(parsed["type"] == 1):
            chat = {
                "id": str(uuid.uuid4()),
                "body": parsed["body"],
                "name": parsed["name"],
                "type": parsed["type"]
                }
            chat["html"] = tornado.escape.to_basestring(
                self.render_string("message.html", message=chat))
 
            ChatSocketHandler.update_cache(chat)
            ChatSocketHandler.send_updates(chat)
        if(parsed["type"] == 2):
            print 'adduser start ...'
            user = {
                "id": str(uuid.uuid4()),
                "content": parsed["content"],
                "type": parsed["type"]
                }
            user["html"] = tornado.escape.to_basestring(
                self.render_string("user.html", user=user))
            self.user = user
            ChatSocketHandler.update_user(user)
            ChatSocketHandler.send_updates(user)
 
 
 
def main():
    tornado.options.parse_command_line()
    app = Application()
    app.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()
 
 
if __name__ == "__main__":
    main()